;------THIS IS A BIOS FOR CPM 2.2 USEING A HARD DISK & 2 FLOPPY DISKS----------
;
;THE FLOPPY'S CAN BE EITHER SINGLE OR DOUBLE DENSITY THE BIOS WILL FIGURE IT
;OUT AUTOMATICALLY. IT IS SETUP AT THE MOMENT FOR ONE SEGATE ST-506 DRIVE &
;ONLY 2 8" DRIVES CONTROLLED BY THE 1791 CHIP. THIS BIOS IS VERY HARDWARE
;DEPENDENT AND WOULD REQUIRE SOME REWORKING FOR OTHERE S-100 BOARDS
;
;THE S100 BOARDS ARE THE VERSAFLOPPY II AND THE XCOMP HARD DISK CONTROLLER
; (BOTH OF THESE ARE FIRST CLASS BORDS IN MY OPINION)
;
;	AUTHOR:	JOHN J. MONAHAN		(201)779-0635		8/6/81
;
;NOTE THIS BIOS IS ~2.5K LONG SO ONE COMPLETE TRACK OF THE 506 DRIVE IS REQ TO
;HOLD THE CP/M SYSTEM (IE 32 256 BYTE SECTORS). ALSO REMEMBER DUREING A SAVE OF
;A REBUILT MEMORY IMAGE (TO USE FOR EXAMPLE IN SYSGEN), SAVE 38 PAGES OF RAM.
;YOU WILL ALSO NEED TO WRITE A SYSGEN PROGRAM TO PUT THIS BIOS ON THE HARD DISK
;A BOOT (IN ROM) TO READ IN THE CPM LOADER (SECTOR 1) AND THE LOADER ITSELF.
;THESE PROGRAMS ARE SUPPLIED BY XCOMP. 
;
ZAPPLE	EQU  0F000H		;SYSTEM MONITOR
MSIZE	EQU  60			;MEMORY SIZE IN KBYTES.
CPMBASE	EQU  (MSIZE-22)*1024  	;BIAS FOR CPM LARGER THAN 17K.(NOTE I ALLOW AN 
				;EXTRA 1K TO MAKE ROOM FOR EXTRA CODE REQ.
CCP	EQU  CPMBASE+3400H	;START OF CPM
BDOS	EQU  CCP+806H		;LINK TO BDOS
BIOS	EQU  CCP+1600H		;START OF BIOS
;
NSECT:	EQU	(BIOS-CCP)/128	;NUMBER SECTORS TO WARM BOOT
IOBYT:	EQU	3	     	;I/O SYSTEM CONFIGURATION
CDISK:	EQU	4	     	;CURRENT DISK ADDRESS (USED BY CPM)
BUFF:	EQU	80H	     	;FCB BUFFER
VSA:	EQU	8	     	;SEEK VERIFY START ADDRESS
VCA:	EQU	1BH	     	;SEEK VERIFY COMPARE ADDRESS
;
;------- HARD DISK PARAMETERS --------------------------------------
;
MAXSEC:	EQU	32	     	;NUMBER OF SECTORS PER TRACK ON HARD DISK
MAXHED:	EQU	4	     	;NUMBER OF HEADS ON HARD DISK
MAXCYL:	EQU	153	     	;NUMBER OF CYLINDERS/HEAD (ST-506)
BLKSIZ:	EQU	2048	     	;NUMBER OF BYTES PER BLOCK FOR HARD DISK
CPMSPT:	EQU	2*MAXSEC     	;NUMBER OF CPM SECTORS PER TRACK FOR HARD DISK
HSKCMD:	EQU	3	     	;SEEK COMMAND FOR HARD DISK CONTROLLER
NOPC:	EQU	40H	     	;NO PRE-COMPENSATION
LOWRT:	EQU	80H	     	;LOW WRITE CURRENT
READY:	EQU	1	     	;HARD DISK DRIVE READY
WRTFLT:	EQU	2	     	;HARD DISK WRITE FAULT
TK00:	EQU	4	     	;HARD DISK TRACK ZERO
RAWINDX:EQU	20H	     	;HARD DISK RAW INDEX
BANK0:	EQU	0	     	;BANK 0 SELECT ON XCOMP CONTROLLER
BANK1:	EQU	1	     	;BANK 1 SELECT
DBENB:	EQU	2	     	;DATA BUFFER ENABLE
CBENB:	EQU	4	     	;COMPARE BUFFER ENABLE
START:	EQU	8	     	;START COMMAND FOR XCOMP CONTROLLER
CBASE:	EQU	70H	     	;BASE ADR OF THE XCOMP CONTROLLER PORTS
DRCSR:	EQU	CBASE	     	;DRIVE COMMAND/STATUS
EXTCMD:	EQU	CBASE+1	     	;EXTENDED COMMNAND REGISTER
LOSC:	EQU	CBASE+2	     	;SEEK COUNT, LSB
HISC:	EQU	CBASE+3	     	;SEEK COUNT, MSB
CTCSR:	EQU	CBASE+4	     	;CONTROLLER COMMAND/STATUS
CTBFR:	EQU	CBASE+5	     	;CONTROLLER BUFFER ADDRESS
CTDP:	EQU	CBASE+6	     	;CONTROLLER DATA PORT
;
;------	FLOPPY DISK PARAMETERS ---------------------------------
;
X	EQU	60H		;BASE ADDRESS OF PORTS FOR 1791
RSET	EQU	X+0		;CONTROLLER RESET ADDRESS
SELECT	EQU	X+3		;DRIVE SELECT PORT
STATUS	EQU	X+4		;STATUS PORT
TRACK	EQU	X+5		;TRACK PORT
SECTOR	EQU	X+6		;SECTOR PORT
DATA	EQU	X+7		;DATA PORT
CMD	EQU	X+4		;COMMAND PORT
RDACMD	EQU	0C0H		;READ ADDRESS CODE
RDCMD	EQU	088H		;READ SECTOR CODE
WRCMD	EQU	0A8H		;WRITE SECTOR CODE
WRTCMD	EQU	0F4H		;WRITE TRACK CODE
RSCMD	EQU	009H		;RESTORE COMMAND
SKNCMD	EQU	019H		;SEEK NO VERIFY
SKCMD	EQU	1DH		;SEEK WITH VERIFY
STDSDT	EQU	26		;STANDARD 8" 26 SECTORS/TRACK
STDDDT	EQU	50		;STANDARD DD 8" 50 SECTORS/TRACK
NBYTES	EQU	128		;BYTES/SECTOR 
NTRKS	EQU	77		;TRACKS/DISK
;
UNIT	EQU	40H		;STORE FOR FLOPPY NEW UNIT BYTE
ERMASK	EQU	41H		;FLOPPY ERROR MASK
ERSTAT	EQU	42H		;FLOPPY ERROR FLAG STORE
CMDSV	EQU	43H		;COMMAND SAVE 
SPSV	EQU	44H		;SP SAVE 
TEMP2	EQU	46H		;2 BYTE TEMP RECORD
COUNT	EQU	48H		;SECTORS/TRACK STORE
UNITCK	EQU	49H		;OLD FLOPPY UNIT BYTE
RSEEK	EQU	4AH		;NBR OF RESEEKS
RTRY	EQU	4BH		;NBR OF RTRYS
ADRIVE	EQU	4CH		;STORE OF A: DRIVE DENSITY ETC TYPE
BDRIVE	EQU	4DH		;STORE OF B: DRIVE TYPE
IDSV	EQU	50H		;6 BYTES (USED FOR TRACK ID COMMAND)
;
;   ASCII CHARACTERS
;
CR:	EQU	0DH	     ;CARRIAGE RETURN
LF:	EQU	0AH	     ;LINE FEED
BELL:	EQU	7	     ;DING
;
;
	ORG	BIOS
;
;	---JUMP TABLE---
;
;
	JP	BOOT	     ;  0 - COLD BOOT
WBX:	JP	WBOOT	     ;  1 - WARM BOOT
	JP	ZAPPLE+12H   ;  2 - CONSOLE STATUS REQUEST
ZCI:	JP	ZAPPLE+03H   ;  3 - CONSOLE INPUT
ZCO:	JP	ZAPPLE+09H   ;  4 - CONSOLE OUTPUT
ZLO:	JP	ZAPPLE+0FH   ;  5 - LIST OUTPUT
	JP	ZAPPLE+0CH   ;  6 - PUNCH OUTPUT
	JP	ZAPPLE+06H   ;  7 - READER INPUT
	JP	HOME	     ;  8 - TRACK ZERO SEEK
	JP	SETDR	     ;  9 - SET DRIVE #
	JP	SETTK	     ; 10 - SET TRACK ADR
	JP	SETSEC	     ; 11 - SET SECTOR ADR
	JP	SETDMA	     ; 12 - SET BUFFER ADDRESS
	JP	READ	     ; 13 - READ A SECTOR
	JP	WRITE	     ; 14 - WRITE A SECTOR
ZLISTS:	JP	ZAPPLE+27H   ; 15 - LIST OUTPUT READY TEST
	JP	SXR	     ; 16 - SECTOR XLATE ROUTINE
;
;	======================
;	** DISK DEFINITIONS **
;	======================
;
DPHDR:	DEFW	0,0	     	;SEAGATE ST-506 DRIVE (DRIVE A:)
	DEFW	0,0
	DEFW	DIRBUF,HDBLK
	DEFW	LAST,HALL0	;LAST & FIRST LOCATIONS FOR BIT-MAP
;
	DEFW	XLT0,0		;FLOPPY 8" SD (DRIVE B:)
	DEFW	0,0
	DEFW	DIRBUF,DPB0
	DEFW	CSV0,ALV0
;
	DEFW	XLT0,0		;FLOPPY 8" SD (DRIVE C:)
	DEFW	0,0
	DEFW	DIRBUF,DPB0
	DEFW	CSV1,ALV1
;
	DEFW	XLT1,0		;FLOPPY 8" DOUBLE DEN (FOR CPM = D:)
	DEFW	0,0		;(FOR HARDWARE DRIVE B: CF. ROM BIOS)
	DEFW	DIRBUF,DPB1
	DEFW	CSV2,ALV2
;
	DEFW	XLT1,0		;FLOPPY 8" DOUBLE DEN (FOR CPM = E:)
	DEFW	0,0		;(FOR HARDWARE DRIVE C: CT. ROM BIOS)
	DEFW	DIRBUF,DPB1
	DEFW	CSV3,ALV3
;
;	---THE HARD DISK PARAMETER BLOCK IS SETUP AS FOLLOWS---
;
;	1. THE SEAGATE ST-506 IS CONFIGURED AS A SINGLE 5.0 MEGABYTE DRIVE.
;
;	2. THE CPM LOGICAL BLOCK SIZE IS 2048 BYTES.
;
;	3. THERE ARE 1024 DIRECTORY ENTRIES. THIS IS THE MOST
;	   WE CAN GET WITH A BLOCK SIZE OF 2048.
;
;	4. THE FIRST TRACK IS RESERVED FOR THE SYSTEM. THIS WILL
;	   ALLOW AN AGGREGATE CCP/BDOS/CBIOS SIZE OF 8 K-BYTES.
;
;
HDBLK:	DEFW	64	     ;SPT: (LOGICAL) SECTORS PER TRACK
	DEFB	4	     ;BSH: BLOCK SHIFT FACTOR
	DEFB	15	     ;BLM: BLOCK MASK
	DEFB	0	     ;EXM: NULL MASK
	DEFW	2441	     ;DSM: (DISK SIZE) - 1
	DEFW	1023	     ;DRM: (DIR SIZE) - 1
	DEFB	0FFH	     ;AL0: DIRECTORY ALLOCATION BITS, MSB
	DEFB	0FFH	     ;AL1:   * LSB
	DEFW	0	     ;CKS: CHECK SIZE
	DEFW	2	     ;OFF: TRACK OFFSET
;
;--- THE FLOPPYS CAN BE SD OR DD SO 2 LOGICAL DRIVE TYPES---
;
;		DRIVES B: & C:
;      	(DISKDEF 0,1,26,6,1024,243,64,64,2)
;
DPB0:  	DW	26		;SEC PER TRACK
     	DB	3		;BLOCK SHIFT
       	DB	7		;BLOCK MASK
      	DB	0		;EXTNT MASK
      	DW	242		;DISK SIZE-1
      	DW	63		;DIRECTORY MAX
      	DB	192		;ALLOC0
       	DB	0		;ALLOC1
     	DW	16		;CHECK SIZE
     	DW	2		;OFFSET
;
XLT0:	DB	1,7,13,19,25,5,11,17,23,3,9,15,21,2,8
	DB	14,20,26,6,12,18,24,4,10,16,22
;
;	----- DRIVE D: & E: ARE DOUBLE DENSITY----
;        (DISKDEF 2,1,50,0,2048,234,64,64,2)
;
DPB1:  	DW	50		;SEC PER TRACK
     	DB	4		;BLOCK SHIFT
    	DB	15		;BLOCK MASK
      	DB	1		;EXTNT MASK
    	DW	233		;DISK SIZE-1
    	DW	63		;DIRECTORY MAX
     	DB	128		;ALLOC0
     	DB	0		;ALLOC1
     	DW	16		;CHECK SIZE
      	DW	2		;OFFSET
;
XLT1:	DB	1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19
	DB	20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36
	DB	37,38,39,40,41,42,43,44,45,46,47,48,49,50
;                
;
;		=====================
;		** CBIOS FUNCTIONS **
;		=====================
;		  ---COLD BOOT---
;
;
BOOT:	LD	SP,BUFF	     	;USE LOW MEMORY
	LD	HL,FLAGS	;CLEAR RAM STORAGE AREA
	LD	B,FLGSIZ
	XOR	A
INIT1:	LD	(HL),A	     	;CLEAR FLAGS & VARIABLES
	INC	HL
	DEC	B
	JP	NZ,INIT1
	LD	(CDISK),A    	;FOR USE BY CPM
	LD	(IOBYT),A	;CLEAR IOBYTE
	DEC	A		;PUT 0FFH IN FLOPPY A & B STORE 
	LD	(ADRIVE),A
	LD	(BDRIVE),A
	JP	XIT	  	;GOTO CPM
;
;	---WARM BOOT---
;
;
WBOOT:	LD	SP,BUFF
	XOR	A
	LD	(RRDSK),A 	;SLCT DRIVE ZERO
	DEC	A
	LD	(ADRIVE),A	;PUT 0FFH IN FLOPPY A & B STORE
	LD	(BDRIVE),A
	CALL	XSTZ	     	;SEEK TO TRACK ZERO
	LD	HL,CCP	     	;CPM LOAD ADR
	LD	(DMADR),HL   	;SAVE IT
	LD	C,2
	CALL	SETSEC	     	;SET SECTOR ADR
	LD	A,NSECT	     	; # SECTORS TO WARM BOOT
WB1:	LD	(SECNT),A    	;SAVE THE SECTOR COUNT
	CALL	HDREAD	     	;READ A SECTOR FROM THE HARD DISK
	OR	A
	JP	Z,WB2	     	;JIF READ OK
	LD	HL,MSG1	     	;  'CAN'T BOOT'
	CALL	PRNT	     	;PRINT ERROR MSG
	JP	ZAPPLE
WB2:	LD	HL,(DMADR)
	LD	DE,128
	ADD	HL,DE	     	;BUMP DMA ADR
	LD	(DMADR),HL
	LD	HL,RRSEC
	LD	C,(HL)
	INC	C	     	;INCR SECT ADR
	CALL	SETSEC	     	;SET NEW SECT ADR
	LD	A,(SECNT)    	;A = SECTOR COUNT
	DEC	A
	JP	NZ,WB1	     	;JIF MORE TO READ
;
;	---EXIT TO CPM---
;
XIT:	LD	HL,BUFF
	LD	(DMADR),HL   ;INIT DMA ADR
	LD	A,0C3H	     ;JMP INST
	LD	(0),A
	LD	HL,WBX
	LD	(1),HL	     ;SET WARM BOOT LINK
	LD	HL,BDOS
	LD	(5),A
	LD	(6),HL	     ;SET BDOS LINK
	LD	A,(CDISK)    ;CURRENT LOGGED-IN DISK & USER
	LD	C,A
	JP	CCP	     ;GOTO CPM
;
;	---SECTOR TRANSLATE ROUTINE---
;
SXR:	EX	DE,HL	     ;H/L = ADR OF XLATE TABLE
	LD	A,L
	OR	H	     ;TEST TABLE ADR
	JP	NZ,SXR1	     ;JIF DO XLATE
	ADD	HL,BC	     ;DON'T XLATE -- USE SECT ADR AS IS
	RET	
;
SXR1:	ADD	HL,BC	     ;INDEX INTO THE TABLE
	LD	L,(HL)	     ;L = XLATED SECTOR ADR
	LD	H,0	     ;H = 0 FOR 16-BIT VALUE
	RET	
;
;	---HOME---
;
;
HOME:	LD	A,(RRDSK)    	;DRIVE #
	CP	1		;SET AT THE MOMENT FOR ONE HARD DISK
	JP	C,XSTZ	     	;JIF REZERO HARD DISK
	CP	3		;ALLOW TWO FLOPPYS
	JP	C,FHOME		;JIF REZERO FLOPPY
SELERR:	LD	A,1	     	;SET ERROR FLAG
	RET	
;
;	---READ---
;
READ:	LD	A,(RRDSK)    	;DRIVE #
	CP	1
	JP	C,HDREAD     	;JIF READ FROM H/D
	CP	3
	JP	C,FREAD		;JIF READ FROM F/D
	JP	SELERR	     	;ABORT, SELECT ERROR
;
;	---WRITE---
;
;
WRITE:	LD	A,(RRDSK)    	;DRIVE #
	CP	1
	JP	C,HDWRT	     	;JIF WRITE ONTO H/D
	CP	3
	JP	C,FWRITE	;JIF WRITE ONTO F/D
	JP	SELERR	     	;ABORT, SELECT ERROR
;
;	---SET DRIVE NUMBER---
;
SETDR:	LD	A,C	     	;A = NEW DRIVE #
	LD	(RRDSK),A    	;  SAVE IT
	LD	HL,0
	CP	3
	RET	NC	     	;RIF INVALID DRIVE # WITH [HL]=0
	CP	1		;IF NOT 1 MUST BE FLOPPYS
	CALL	NC,FSELDSK	;RETURNS WITH LOGICAL DRIVE OFFSET IN [A]
	LD	L,A
	ADD	HL,HL	     	;SHIFT H/L LEFT 4
	ADD	HL,HL	     	;   (HL = HL*16)
	ADD	HL,HL
	ADD	HL,HL
	LD	DE,DPHDR     	;DISK PARM HDR
	ADD	HL,DE	     	;H/L = DPHDR FOR SELECTED DRIVE
	RET	
;
;	---SET SECTOR ADR---
;
SETSEC:	LD	A,C
	LD	(RRSEC),A    ;SAVE SECTOR ADR
			     ;SET REAL SECTOR ADR FOR THE H/D DRIVER
	AND	NOT 1	     ;CLEAR LOW ORDER BIT
	RRCA		     ;THERE ARE 2 CPM SECTORS PER H/D SECT
	LD	(RSA),A	     ;SAVE REAL SECTOR ADR
	RET
;	
;	---SET TRACK ADDRESS---
;
;
SETTK:	LD	H,B
	LD	L,C
	LD	(RRTRK),HL   ;SAVE TRACK ADR
	RET
;
;	---SET DMA ADDRESS---
;
;
SETDMA:	LD	H,B
	LD	L,C
	LD	(DMADR),HL   ;SAVE DMA ADR
	RET	
;
;	======================================
;	** HARD DISK BLOCK/DEBLOCK ROUTINES **
;	======================================
;
;	---HARD DISK READ---
;
HDREAD:	XOR	A
	LD	(ERFLG),A    ;CLEAR THE ERROR FLAG
	LD	A,(FLAGS)    ;SET READ OPERATION FLAG
	SET	0,A     
	BIT	2,A          ;WRITE IN PROGRESS ?
	LD	(FLAGS),A
	CALL	NZ,XWRT	     ;YES, WRITE DATA BEFORE READ
	LD	A,(FLAGS)
	RES	2,A          ;RESET 'WIP' FLAG
	LD	(FLAGS),A
	CALL	TSTHST	     ;HOST = REQ ?
	JP	NZ,HDRD1     ;NO, READ A BLOCK
	LD	A,(FLAGS)
	BIT	1,A    	     ;PRIOR BLOCK READ ?
	JP	NZ,HDRD2     ;YES, JUST EXTRACT DATA FROM BFR
HDRD1:	CALL	SETHST	     ;MAKE HOST=REQ
	CALL	XREAD	     ;READ A BLOCK
HDRD2:	CALL	GETDMA	     ;GET DMA ADR, SET POINTERS
	IN	A,CTDP	     ;PRIME DATA INPUT
	INIR		     ;BLOCK INPUT
	LD	A,(FLAGS)
	SET	1,A    	     ;SET READ-IN-PROGRESS FLAG
	LD	(FLAGS),A
	LD	A,(ERFLG)    ;ERROR FLAG
	RET
;	
;	---HARD DISK WRITE---
;
;
HDWRT:	XOR	A
	LD	(ERFLG),A    ;CLEAR THE ERROR FLAG
	LD	A,(FLAGS)
	RES	1,A    	     ;CLEAR READ-IN-PROGRESS FLAG
	LD	(FLAGS),A
	LD	A,C	     ;A = WRITE MODE
	DEC	A
	JP	Z,WDIR	     ;DO DIRECTORY WRITE
	JP	M,WNORM	     ;DO NORMAL WRITE
;
;   UNALLOCATED WRITE
;
WUN:	LD	A,(FLAGS)
	BIT	2,A    	     ;WRITE IN PROGRESS ?
	CALL	NZ,XWRT	     ;YES, WRITE DATA IN BFR
			     ;SET UNALLOC RECORD PARAMETERS
	LD	A,BLKSIZ/128
	LD	(URCNT),A    ;SET UNALLOC RECORD COUNT
	LD	HL,(RRDSK)
	LD	(URDSK),HL   ;UPDATE DRIVE & SECTOR
	LD	HL,(RRTRK)
	LD	(URTRK),HL   ;UPDATE TRACK ADR
	CALL	SETHST	     ;SET HOST = REQ
	CALL	BUMP	     ;BUMP UNALC PARMS FOR NEXT PASS
			     ;XFER DATA TO CTLR BFR
WXFER:	LD	A,(FLAGS)
	RES	0,A          ;CLEAR READ OPER FLAG
	LD	(FLAGS),A
	CALL	GETDMA	     ;GET DMA ADR, SET FOR WRITE
	OTIR		     ;BLOCK OUTPUT
	LD	A,(FLAGS)
	SET	2,A    	     ;SET WRITE-IN-PROGRESS FLAG
	LD	(FLAGS),A
	LD	A,(ERFLG)    ;ERROR FLAG
	RET	
;
;   NORMAL WRITE
;
WNORM:	LD	A,(URCNT)    ;UNALC RECORD COUNT
	OR	A
	JP	Z,WALC	     ;JIF DO ALLOC WRITE
	LD	HL,URTRK
	CALL	DSKCMP	     ;UNALC DSK/TRK = REQ DSK/TRK ?
	JP	NZ,WALC	     ;NO, DO ALLOC WRITE
	LD	A,(RRSEC)
	CP	(HL)	     ;UNALC SECT = REQ SECT ?
	JP	NZ,WALC	     ;NO, DO ALLOC WRITE
	CALL	BUMP	     ;BUMP UNALC PARMS FOR NEXT PASS
	CALL	TSTHST	     ;HOST = REQ ?
	JP	Z,WN1	     ;YES, CON'T TO FILL THE BFR
	LD	A,(FLAGS)	
	BIT	2,A    	     ;WRITE IN PROGRESS ?
	CALL	NZ,XWRT	     ;YES, WRITE OLD DATA ONTO DISK
	CALL	SETHST	     ;MAKE HOST = REQ
;
WN1:	LD	A,(FLAGS)
	BIT	0,A          ;INTERVENING READ ?
	CALL	NZ,XREAD     ;YES, READ OLD UNALC DATA
	JP	WXFER	     ;MOVE DATA TO BFR, EXIT
;
;   ALLOCATED WRITE
;
WALC:	XOR	A
	LD	(URCNT),A    ;CLEAR UNALC RECORD COUNT
	CALL	TSTHST	     ;HOST = REQ ?
	JP	Z,WXFER	     ;YES -  MOVE DATA TO BFR, EXIT
	LD	A,(FLAGS)
	BIT	2,A    	     ;WRITE IN PROGRESS ?
	CALL	NZ,XWRT	     ;YES, WRITE OLD DATA ONTO DISK
	CALL	SETHST	     ;MAKE HOST = REQ
	CALL	XREAD	     ;READ IN ALLOCATED DATA
	JP	WXFER	     ;MOVE NEW DATA IN BFR, EXIT
;
;   DIRECTORY WRITE
;
WDIR:	XOR	A
	LD	(URCNT),A    ;CLEAR UNALC RECORD COUNT
	LD	A,(FLAGS)
	RES	0,A          ;RESET 'RDOP' FLAG
	LD	(FLAGS),A
	BIT	2,A    	     ;WRITE IN PROGRESS ?
	CALL	NZ,XWRT	     ;YES, WRITE OLD DATA ONTO THE DISK
	LD	A,(FLAGS)
	RES	2,A    	     ;CLEAR 'WIP' FLAG
	LD	(FLAGS),A
	CALL	SETHST	     ;MAKE HOST = REQ
	CALL	XREAD	     ;READ DIR DATA
	RET	NZ	     ;RIF READ ERROR
	CALL	GETDMA	     ;GET DMA ADR, SET POINTERS
	OTIR		     ;BLOCK OUTPUT
	JP	XWRT	     ;WRITE DIR DATA, EXIT
;
;	---TEST HOST---
;
;   DETERMINES IF THE HOST DISK ADDRESS IS
;   THE SAME AS THE REQUESTED DISK ADDRESS.
;
;
TSTHST:	LD	HL,HHTRK
	CALL	DSKCMP	     ;TRACK & DRIVE THE SAME ?
	RET	NZ	     ;RIF NO
	LD	A,(RSA)
	CP	(HL)	     ;SECTOR THE SAME ?
	RET		     ;IF A = 0 THEN THEY MATCH
;
;	---SET HOST---
;
;   SETS THE HOST DISK ADDRESS TO BE THE
;   SAME AS THE REQUESTED DISK ADDRESS.
;
;
SETHST:	LD	A,(RRDSK)
	LD	(HHDSK),A    ;DRIVE #
	LD	HL,(RRTRK)
	LD	(HHTRK),HL   ;TRACK ADR
	LD	A,(RSA)
	LD	(HHSEC),A    ;SECTOR ADR
	RET	
;
;	---BUMP---
;
;   BUMPS PARAMETERS FOR UNALLOCATED WRITES.
;   PARMS ARE CHANGED FOR THE NEXT PASS THRU
;   THE CODE (NOT THE CURRENT PASS).
;
BUMP:	LD	HL,URCNT     ;UNALC RECORD COUNT
	DEC	(HL)	     ;  DECR IT
	DEC	HL	     ;H/L = URSEC
	INC	(HL)	     ;  INCR IT
	LD	A,(HL)
	CP	CPMSPT	     ;CPM SECTORS PER TRACK
	RET	C	     ;RIF STAY ON SAME TRACK
			     ;OVERFLOW TO NEXT TRACK
	LD	(HL),0	     ;RESET SECTOR ADR
	LD	HL,(URTRK)
	INC	HL	     ;INCR TRACK ADR
	LD	(URTRK),HL
	RET	
;
;	---GET DMA ADDRESS---
;
;   SETS THE CONTROLLER BUFFER ADDRESS TO THE CORRECT
;   STARTING POINT. ALSO SETS B=128 & H/L=DMADR.
;
;
GETDMA:	LD	HL,(DMADR)   ;DMA ADR
	LD	C,CTDP	     ;FOR BLOCK I/O
	LD	B,128	     ;B = COUNT
	LD	A,DBENB
	OUT	CTCSR,A	     ;ENB DATA BFR
	LD	A,(RRSEC)    ;REQUESTED SECTOR
	RRCA	
	LD	A,0
	JP	NC,GET1	     ;JIF USE 1ST HALF OF BFR
	LD	A,B	     ;   USE 2ND HALF OF BFR
GET1:	OUT	CTBFR,A	     ;SET CTLR DATA BFR ADR
	RET	
;
;
;	======================================
;	** HARD DISK I/O & SUPPORT ROUTINES **
;	======================================
;	---READ A BLOCK---
;
XREAD:	LD	HL,RTBL	     ;READ CMD TBL
	CALL	DORW	     ;READ
;
XR1:	LD	A,0
	RET	Z	     ;RIF READ/WRITE OK
	INC	A
	LD	(ERFLG),A    ;SET ERROR FLAG
	RET	
;
;	---WRITE A BLOCK---
;
XWRT:	LD	HL,WTBL	     ;WRITE CMD TBL
	CALL	DORW	     ;WRITE A SECTOR
	JP	XR1	     ;SET ERROR FLAG
;
;	---EXECUTE READ/WRITE COMMANDS---
;
DORW:	PUSH	HL	     ;SAVE CMD TBL ADR
	CALL	XSEK	     ;SEEK TO NEW TRACK (IF REQUIRED)
	POP	HL	     ;RESTORE CMD TBL ADR
	RET	NZ	     ;RIF SEEK FAILED
	CALL	XSEL	     ;HEAD SELECT
;
DO0:	LD	A,(HL)
	LD	(RETRY),A    ;SET RETRY COUNT
	INC	HL
	LD	A,(HL)
	OUT	CTCSR,A	     ;ENB CMP BFR
	INC	HL
	LD	A,(HL)
	OUT	CTBFR,A	     ;SET CMP BFR ADR
	INC	HL
	LD	(CTA),HL     ;SAVE CMD TBL ADR
;
	LD	HL,RTK	     ;REAL TK ADR
	LD	B,3
DO1:	LD	A,(HL)
	OUT	CTDP,A	     ;PUT HDR INFO INTO CMP BFR
	INC	HL
	DEC	B
	JP	NZ,DO1
	LD	A,(HHSEC)
	OUT	CTDP,A	     ;SET SECT ADR FOR COMPARE
;
DO2:	CALL	XRDY	     ;DRIVE READY ?
	RET	NZ	     ;  RIF NO
	LD	HL,(CTA)     ;CMD TBL ADR
	LD	A,(HL)	     ;A = CNTL BANK
	INC	HL
	LD	B,A
	OUT	CTCSR,A	     ;SLCT CNTL BANK
	LD	A,(HL)
	OUT	CTBFR,A	     ;SET START ADR
	INC	HL
	LD	A,B
	OR	START
	OUT	CTCSR,A	     ;START R/W CMD
;
DO3:	CALL	WFD	     ;WAIT FOR READ/WRITE TO FINISH
	AND	(HL)	     ;TEST CTLR STATUS (0=OK)
	LD	B,A
	IN	A,DRCSR	     ;DRIVE STATUS
	AND	WRTFLT
	CALL	NZ,CLRDF     ;CIF CLEAR DRIVE FAULT
	OR	B	     ;SET/CLEAR ERROR FLAG (0=OK)
	RET	Z	     ;RIF READ/WRITE OK
	LD	HL,RETRY
	DEC	(HL)	     ;DECR RETRY COUNT
	JP	NZ,DO2	     ;JIF RETRY READ/WRITE
;
;   SET ERROR FLAG
;
SEF:	LD	A,1	     ;A = ERROR FLAG
	OR	A	     ;SET 8080 FLAGS
	RET		     ;TAKE ERROR EXIT
;
;	---WAIT FOR DONE---
;
WFD:	IN	A,CTCSR	     ;CTLR STATUS
	RRCA	
	JP	NC,WFD	     ;WAIT FOR DONE
	NOP		     ;DELAY FOR H/W
	IN	A,CTCSR	     ;GET NON-CHANGING STATUS
	LD	B,A	
	XOR	A
	OUT	CTCSR,A	     ;STOP CTLR
	LD	A,B
	RET	
;
;	---REZERO---
;
XTKZ:	CALL	XRDY	     ;DRIVE READY ?
	RET	NZ	     ;   RIF NO
	LD	HL,0
	LD	(CHDT),HL    ;SET CURRENT TRACK = 0
	LD	B,0	     ;SET RETRY COUNT = 256
;
XTKZ1:	IN	A,DRCSR	     ;DRIVE STATUS
	AND	TK00	     ;TRACK ZERO INDICATOR
	XOR	TK00	     ;  MAKE IT LO-TRUE
	RET	Z	     ;RIF AT TRACK ZERO
	DEC	B	     ;DECR RETRY CNT
	JP	Z,SEF	     ;JIF REZERO FAILED
	XOR	A
	OUT	HISC,A
	INC	A
	OUT	LOSC,A	     ;SET SEEK COUNT = 1
	OUT	EXTCMD,A     ;SET SEEK DIRECTION = OUT
	LD	A,HSKCMD
	OUT	DRCSR,A	     ;START SEEK
	CALL	WSC	     ;WAIT FOR SEEK DONE
	JP	XTKZ1
;
;	---SEEK TO TRACK ZERO---
;
XSTZ:	LD	A,(FLAGS)
	BIT	2,A    
	JP	NZ,XSTZ1     ;JIF WRITE IN PROGRESS
	LD	(FLAGS),A    ;MAKE HOST INACTIVE
XSTZ1:	LD	HL,0
	LD	(RRTRK),HL   ;SET TK ADR = 0
	XOR	A	     ;SET FLAG = NO ERRORS
	RET
;
;	---SEEK---
;
XSEK:	CALL	XRDY	     ;DRIVE READY ?
	RET	NZ	     ;  RIF NO
	LD	A,3
	LD	(RETRY),A    ;SET RETRY COUNT
;
XSEK1:	XOR	A
	OUT	HISC,A	     ;SET MSB OF SEEK COUNT = 0
	LD	HL,(HHTRK)   ;REQUESTED TRACK
	LD	B,2
	CALL	DRS	     ;SHIFT H/L RIGHT TWICE
	LD	(RTK),HL     ;SAVE REAL TK ADR
	LD	A,L
	SUB	MAXCYL AND 0FFH
	LD	A,H
	SBC	MAXCYL SHR 8
	JP	NC,SEF	     ;JIF INVALID CYL ADR
	LD	A,L	     ;A = TARGET CYL ADR
	LD	B,L	     ;FOR LATER USE
	LD	C,3	     ;DIRECTION = INWARD
	LD	HL,CHDT	     ;CURR TK ADR
	SUB	(HL)
	RET	Z	     ;RIF AT REQUESTED TK
	LD	(HL),B	     ;UPDATE CURR TK ADR
	JP	NC,XSEK2     ;JIF SEEK INWARD
	CPL	
	INC	A	     ;MAKE SEEK CNT POSITIVE
	LD	C,1	     ;MAKE DIRECTION = OUTWARD
XSEK2:	OUT	LOSC,A	     ;SET SEEK COUNT
	LD	A,C
	OUT	EXTCMD,A     ;SET DIRECTION OF SEEK
	LD	A,HSKCMD
	OUT	DRCSR,A	     ;INITIATE SEEK
	CALL	WSC	     ;WAIT FOR SEEK DONE
			     ;SEEK VERIFY
	LD	A,CBENB
	OUT	CTCSR,A	     ;ENABLE BANK ZERO CMP BFR
	LD	A,VCA
	OUT	CTBFR,A	     ;SET CMP BFR ADR
	LD	A,(CHDT)
	OUT	CTDP,A	     ;SET CYL ADR, LSB
	XOR	A
	OUT	CTDP,A	     ;SET CYL ADR, MSB
	LD	A,VSA
	OUT	CTBFR,A	     ;SET M/CODE START ADR
	LD	A,START
	OUT	CTCSR,A	     ;START VERIFY
	CALL	WFD	     ;WAIT FOR DONE
	AND	0CH	     ;TEST CTLR STATUS
	RET	Z	     ;RIF VERIFY OK
			     ;VERIFY FAILED
	CALL	XTKZ	     ;RESTORE
	LD	HL,RETRY
	DEC	(HL)	     ;DECR RETRY COUNT
	JP	NZ,XSEK1     ;JIF RETRY SEEK
	OR	1	     ;SET FAIL FLAG
	RET		     ;ERROR EXIT
;
;	---WAIT FOR SEEK COMPLETE---
;
WSC:	IN	A,DRCSR	     ;DRIVE STATUS
	RLA	
	JP	NC,WSC	     ;WAIT FOR SEEK DONE
	IN	A,DRCSR	     ;DRIVE STATUS
	AND	WRTFLT	     ;TEST FOR DRIVE FAULT
	RET	Z	     ;RIF OK
;
;	---CLEAR DRIVE FAULT---
;
CLRDF:	XOR	A
	OUT	EXTCMD,A     ;DE-SELECT THE DRIVE (FALL THRU TO 'XSEL' TO
			     ;RE-SELECT THE DRIVE)
;
;	---HEAD SELECT---
;
XSEL:	LD	A,(HHTRK)    ;REQUESTED TRACK
	AND	3	     ;4 HEADS
	LD	(RHD),A	     ;SAVE REAL HEAD #
	ADD	A	     ;SHIFT HEAD # LEFT TWICE FOR H/W
	ADD	A
	OR	1	     ;TO MAINTAIN DRIVE SLCT
	LD	B,A
	LD	A,(CHDT)     ;CURRENT CYLINDER ADR
	CP	MAXCYL/2     ;HALF CYLINDER POINT ?
	LD	A,0	     ;PRE-COMP ST-506 ON ALL CYLS
	JP	C,XSEL1	     ;JIF 1ST HALF OF DISK
	LD	A,LOWRT	     ;LOW WRITE CURRENT
XSEL1:	OR	B	     ;B = HEAD SLCT INFO
	OUT	EXTCMD,A     ;SELECT HEAD 0...3
	RET	
;
;	---DRIVE READY TEST---
;
XRDY:	IN	A,DRCSR	     ;DRIVE STATUS
	AND	1	     ;DRIVE READY BIT
	XOR	1	     ;INVERT IT
	RET		     ;IF A = 0, DRIVE RDY
;
;	---COMMAND TABLES---
;   WRITE
WTBL:	DEFB	5	     ;RETRY COUNT
	DEFB	5	     ;CMP BFR ENB
	DEFB	0E4H	     ;CMP BFR ADR
	DEFB	BANK1	     ;CNTL BANK
	DEFB	0D1H	     ;START ADR
	DEFB	0EH	     ;STATUS MASK
;
;   READ
RTBL:	DEFB	10	     ;RETRY COUNT
	DEFB	4	     ;CMP BFR ENB
	DEFB	0EAH	     ;CMP BFR ADR
	DEFB	BANK0	     ;CNTL BANK
	DEFB	0D7H	     ;START ADDRESS
	DEFB	0EH	     ;STATUS MASK
;
;	---DISK ADDRESS COMPARE---
;
;   COMPARES EITHER THE HOST DISK ADDRESS OR THE UNALLOCATED
;   DISK ADDRESS AGAINST THE REQUESTED DISK ADDRESS.
;
DSKCMP:	LD	DE,RRTRK     ;REQUESTED TRACK
	LD	B,3
DC1:	LD	A,(DE)
	CP	(HL)
	RET	NZ	     ;RIF ADRS NOT EQUAL
	INC	HL
	INC	DE
	DEC	B
	JP	NZ,DC1
	RET	
;
;	======================================
;	 	FLOPPY DISK ROUTINES
;	======================================
;
FHOME:	XOR	A		;NO NEED TO DO ACTUAL HOME AT THIS STAGE
	LD	(RRTRK),A	;WILL ALWAYS BE < 0FF TRACKS ON FLOPPY
	RET
;
FSELDSK:DEC	A		;FOR FLOPPY MAKE B:=A: (OR C:) 
	LD	C,A		;AND C:=B: (OR D:) FOR FLOPPY PARAMETERS
	OR	A		;IF REQUESTED DRIVE IS A: THEN [A] = 0
	JP	NZ,BBBB		;MUST BE B: DRIVE
	LD	A,(ADRIVE)	;IS IT FIRST TIME TO GET THIS DRIVE
	CP	0FFH
	CALL	Z,GETTYPE
	LD	(ADRIVE),A	;STORE DENSITY FLAG
	JP	ALLOK
BBBB:	LD	A,(BDRIVE)	;IS IT FIRST TIME FOR THIS ONE
	CP	0FFH
	CALL	Z,GETTYPE
	LD	(BDRIVE),A	;STORE DENSITY FLAG
;
ALLOK:	OR	C		;MIX DRIVE TYPE WITH DRIVE#
	LD	(UNIT),A	;STORE IT FOR SECTOR R/W ROUTINES ETC
	INC	A		;ADD BACK WHAT WE SUBTRACTED ABOVE
	BIT	6,A
	RET	Z		;RETURNS WITH TABLE OFFSET B:=B: & C:=C:
				;FOR DOUBLE DENSITY DISKS WE MUST USE THE
				;LOOKUP TABLE FOR DRIVES D: & E:
	LD	A,00000011B	;RETURNS FOR TABLE OFFSET B:=D: & C:=E:
	ADD	C		;FOR DOUBLE DENSITY DISKS
	RET	
;
GETTYPE:LD	A,C		;FIND OUT TYPE OF DRIVE
	CALL	UNITSL
	JP	NZ,HB101	;IF NZ PROBLEMS ABORT
	LD	A,(UNIT)
	AND	01000000B	;GET DENSITY FLAG
	RET
;
; THIS ROUTINE SETS UP THE FLOPPY DISK UNIT BYTE
; THE REQUIRED DRIVE IS IN [A]
;
UNITSL:	LD	B,5
	AND	0FH
	OR	40H		;COME UP DEFALT IN 8" DD
	LD	(UNIT),A
	LD	HL,(DMADR)
	LD	(TEMP2),HL
	CALL	USL1
	LD	HL,(TEMP2)
	LD	(DMADR),HL
	LD	A,(UNIT)
	RET	
;
USL1:	PUSH	BC
	PUSH	HL
	LD	(SPSV),SP
	POP	HL
	CALL	DRVSET		;SELECT DRIVE IN HARDWARE
	CALL	IDRD		;TRY READING TRACK ID
	POP	BC
	RET	Z		;IF CORRECT DENSITY WILL BE Z
	DEC	B		;DECREASE 5.......0 IF Z THEN ERROR
	JP	Z,SPECIAL
	CALL	CHGTYP
	JR	USL1
;
SPECIAL:XOR	A		;COULD BE LATER USED FOR SPECIAL SECTOR SIZE
	DEC	A
	RET			;RET NZ SO SELDSK KNOWS THERE IS A PROBLEM
;
CHGTYP:	LD	A,(UNIT)
	ADD	01000000B	;TOGGLE DENSITY BIT
	AND	01111111B	;CLEAR BIT 7
	LD	(UNIT),A
	RET
;
;	READ A SECTOR
FREAD:	LD	BC,301H
READBT:	LD	(RSEEK),BC
READ1:	PUSH	BC
	CALL	RDSC
	POP	BC
	RET	Z
	CALL	FRETRY
	JR	READ1  
;
;	WRITE A SECTOR
FWRITE:	LD	BC,301H
WRBT:	LD	(RSEEK),BC
WRITE1:	PUSH	BC
	CALL	WRSC	
	POP	BC
	RET	Z
	CALL	RETRY
	JR	WRITE1  
;
FRETRY:	DJNZ	RETRY2  
	LD	A,(RTRY)
	LD	B,A
	DEC	C
	JP	P,RETRY1
	POP	AF
	XOR	A
	INC	A
	RET
;
RETRY1:	PUSH	BC
	CALL	HOME1
	POP	BC
RETRY2:	RET
;
HOME1:	LD	(SPSV),SP
	LD	A,RSCMD
	CALL	SEEK4
	XOR	A
	RET
;
;	SELECT DRIVE IN HARDWARE
;
DRVSET:LD	DE,UNIT
	LD	A,(DE)
	AND	0E0H
	LD	C,A		;STORE DRIVE TYPE IN [C]
	LD	A,(DE)
	AND	03
	LD	B,A		;STORE DRIVE # IN [B]
	LD	A,1
	JR	Z,DRVSEL  
CKDRV1:	RLCA
	DJNZ	CKDRV1  
DRVSEL:	OR	C		;COMBINE TYPE & DRIVE#
	AND	7FH
	LD	B,A		;[B] CONTAINS INFO FOR HARDWARE
	LD	A,STDSDT	;SETUP FOR SD
	LD	(COUNT),A	;STORE AS 26 SECTORS/TRACK
	LD	A,40H		;WAS IT DD
DRV1:	CP	C
	JR	NZ,CKDRV
	LD	A,STDDDT	;SETUP FOR DD 
	LD	(COUNT),A	;SET TO 50 SECTORS/TRACK
CKDRV:	LD	A,B		;GET HARDWARE SELECT DATA
	CPL			;HARDWARE IS INVERTED
	OUT	(SELECT),A
	LD	A,(DE)
	LD	(UNITCK),A
	CALL	DELAY
RDYCK:	IN	A,(STATUS)
	AND	80H
	JP	NZ,END2
	RET
;
;	READ PRESENT DISK ADDRESS
IDRD:	CALL	WAIT
	LD	HL,IDSV
	LD	BC,600H+DATA	;READ 6 BYTES
	LD	A,0F8H
	LD	(ERMASK),A
	CALL	SWEB
	LD	A,RDACMD	;DO THE ID READ
	CALL	RDSCO
	LD	A,(IDSV)
	CP	NTRKS		;IS IT REASONABLE
	JP	NC,SEEK0
	OUT	(TRACK),A	
	XOR	A
	RET
;
DELAY:	LD	A,40		;DELAY ~32 MS (DOES NOT SEEM TO BE CRITICAL)
DELAY1:	LD	B,0
M0:	DJNZ	M0
	DEC	A
	JR	NZ,DELAY1  
	RET
;
;	READ SECTOR COMMAND
RDSC:	CALL	DRINIT
	LD	A,RDCMD
RDSCO:	LD	(CMDSV),A
	DI
	OUT	(CMD),A
	JR	M2
M2:	JR	MM2
MM2:	INIR
	EI
	JR	END
;
;
;	WRITE SECTOR COMMAND
WRSC:	CALL	DRINIT
	LD	A,WRCMD
	LD	(CMDSV),A
	DI	
	OUT	(CMD),A
	JR	H2
H2:	JR	HM2
HM2:	OTIR
	EI
;
;	END  OF COMMAND
END:	CALL	WAIT
	IN	A,(STATUS)
	LD	D,A
	LD	A,(ERMASK)
	AND	D
	RET	Z
END1:	LD	A,D
END2:	LD	(ERSTAT),A
	CALL	DELAY
	OR	1
	LD	SP,(SPSV)
	CALL	UNITFX
	RET
;
;
;	DRIVE INITIALIZATION
;
DRINIT:	POP	HL
	LD	(SPSV),SP
	PUSH	HL
	LD	A,(UNIT)
	LD	D,A
	LD	A,(UNITCK)
	CP	D
	JR	Z,DINIT1  
	CALL	DRVSET
	CALL	IDRD
DINIT1:	CALL	SEEK
	LD	A,0FEH
	LD	(ERMASK),A
;
TRINT:	LD	HL,(DMADR)	;SETUP DMA ADDRESS AND BYTE COUNT
	LD	A,(RRSEC)
	OUT	(SECTOR),A
	LD	BC,NBYTES*100H+DATA
;
SWEB:	IN	A,(SELECT)	;ENABLE WAIT STATES
	AND	7FH
	OUT	(SELECT),A
	RET
;
;	SEEK TRACK
;
SEEK:	CALL	RDYCK
	LD	C,NTRKS		;MUST BE REASONABLE TRACK #
	LD	A,(RRTRK)	;ALWAYS < 0FFH TRACKS FOR FLOPPY
	CP	C
	JR	C,SEEK1  
SEEK0:	LD	A,0FH
	JR	END2 
SEEK1:	LD	C,A
	IN	A,(TRACK)
	CP	C
	RET	Z		;IF SAME TRACK NO NEED TO SEEK
	LD	A,SKCMD
SEEK4:	LD	(CMDSV),A
	LD	B,210
S0:	DJNZ	S0
	CALL	WAIT
	LD	A,(RRTRK)
	OUT	(DATA),A
	LD	A,80H
	LD	(ERMASK),A
	LD	A,(CMDSV)
	OUT	(CMD),A
	LD	B,10
D0:	DJNZ	D0
	CALL	END
	CALL	DELAY
	LD	A,(CMDSV)
	CP	RSCMD		;NO NEED TO CHECK RESTORE COMMAND
	RET	Z
	IN	A,(STATUS)
	AND	10H
	JR	NZ,SEEK2
	IN	A,(TRACK)
	CP	C
	RET	Z
SEEK2:	LD	A,20H
END2JP:	JP	END2  
;
WAIT:	LD	E,0
	PUSH	BC
	LD	C,2
WAIT2:	IN	A,(STATUS)
	AND	1
	JR	Z,DWAIT
	DJNZ	WAIT2  
	DEC	E
	JR	NZ,WAIT2
	DEC	C
	JR	NZ,WAIT2
	POP	BC  
	IN	A,(SELECT)		;IF BY THIS TIME NOT READY FORCE
	OR	80H			;A HARDWARE RESET
	OUT	(RSET),A
F0:	DJNZ	F0
	IN	A,(RSET)
	CALL	FRCINT
	LD	A,RSCMD
	CALL	SEEK4
	LD	A,0FEH
	JP	END2JP	
;
;	DISABLE WAIT STATES
DWAIT:	POP	BC			;TO BALANCE THE ABOVE PUSH IN WAIT
	IN	A,(SELECT)
	OR	80H
	OUT	(SELECT),A
	RET
;
;
;
;	FORCE CHIP INTERUPT
FRCINT:	LD	A,0D0H
	OUT	(CMD),A
	LD	A,10
FRC1:	DEC	A
	JR	NZ,FRC1
	IN	A,(STATUS)
	RET
;
UNITFX:	LD	A,0FFH
	LD	(UNITCK),A
	RET
;
;
;	======================================
;	** SUBROUTINES, MESSAGES, & STORAGE **
;	======================================
;
;	---DOUBLE RIGHT SHIFT---
;
;   SHIFTS THE CONTENTS OF H/L RIGHT 'N' TIMES.
;
DRS:	PUSH	AF	     ;SAVE 'A'
DRS1:	LD	A,H	     ;MSB
	OR	A	     ;CLEAR CY
	RRA	
	LD	H,A
	LD	A,L	     ;LSB
	RRA	
	LD	L,A
	DEC	B	     ;B = SHIFT COUNT
	JP	NZ,DRS1
	POP	AF	     ;RESTORE 'A'
	RET	
;
;	---PRINT ROUTINE---
;
;
PRNT:	LD	A,(HL)	     ;PRINT CHAR
	INC	HL	     ;FOR NEXT CHAR
	OR	A
	RET	Z	     ;RIF DONE
	LD	C,A
	CALL	ZCO	     ;PRINT A CHAR
	JP	PRNT	     ;DO NEXT CHAR
;
;
HB101:	LD	HL,0		;ABORT BECAUSE CANNOT GET DISK TYPE
	POP	AF		;DROP STACK BACK ONE LEVEL
	XOR	A
	LD	(CDISK),A	;SO WARMSTART WILL COME UP ON A
	INC	A		;JUST IN CASE
	RET
;
;	---MESSAGES---
;
MSG1:	DEFB	CR,LF,BELL
	DEFB	'Warm boot read error'
	DEFB	CR,LF,0
;
;	---PROGRAM STORAGE---
;
FLAGS:	DEFS	1	     ;BIT FLAGS
			     ;BIT 0 SET FOR READ OPERATION
			     ;BIT 1 SET FOR READ IN PROGRESS
			     ;BIT 2 SET FOR WRITE IN PROGRESS
;
RRTRK	DEFS	2	     ;CP/M REQUESTED TRACK ADDRESS
RRDSK	DEFS	1	     ;CP/M REQUESTED DRIVE #
RRSEC	DEFS	1	     ;CP/M REQUESTED SECTOR
;
URTRK:	DEFS	2	     ;UNALLOCATED TRACK ADDRESS
URDSK:	DEFS	1	     ;   DRIVE #
URSEC:	DEFS	1	     ;   SECTOR ADDRESS
URCNT:	DEFS	1	     ;   RECORD COUNT
;
HHTRK:	DEFS	2	     ;HOST (SHUGART) TRACK ADDRESS
HHDSK:	DEFS	1	     ;   DRIVE #
HHSEC:	DEFS	1	     ;   SECTOR ADDRESS
;
RTK:	DEFS	2	     ;REAL TRACK ADDRESS
RHD:	DEFS	1	     ;  HEAD
RSA:	DEFS	1	     ;  SECTOR
;
SECNT:	DEFS	1	     ;SECTOR COUNT (FOR WARM BOOT)
RETRY:	DEFS	1	     ;RETRY COUNT
CTA:	DEFS	2	     ;COMMAND TABLE ADDRESS
ERFLG:	DEFS	1	     ;ERROR FLAG
DMADR:	DEFS	2	     ;BUFFER (DMA) ADDRESS
WRTMODE:DEFS	1	     ;WRITE MODE
CHDT:	DEFS	2	     ;CURRENT HARD DISK TRACK
TEMP:	DEFS	2	     ;TEMPORARY STORAGE
;
FLGSIZ:	EQU	$-FLAGS	     ;DEFINES SIZE OF VARIABLE STORAGE
;
;	---BDOS STORAGE---
;
DIRBUF:	DS	128	     ;DIRECTORY ACCESS BUFFER
ALV0:	DS	31
CSV0:	DS	16
ALV1:	DS	31
CSV1:	DS	16
ALV2:	DS	30
CSV2:	DS	16
ALV3:	DS	30
CSV3:	DS	16
HALL0:	DS	306	;BIT MAP FOR ST-506
LAST:	EQU	$
;END
